#include "./spi/hard_spi1.h"
#include "debug.h"

#define OPT_DBG_INF 1U

static SPI_HandleTypeDef hspi;

/*SPI Init*/
void Spi1_Init(void)
{
  hspi.Instance                 = SPI1;
  hspi.Init.BaudRatePrescaler   = SPI_BAUDRATEPRESCALER_2;
  #if SPI_MODE_0
  hspi.Init.CLKPhase            = SPI_PHASE_1EDGE;
  hspi.Init.CLKPolarity         = SPI_POLARITY_LOW;
  #elif SPI_MODE_3
  hspi.Init.CLKPhase            = SPI_PHASE_2EDGE;
  hspi.Init.CLKPolarity         = SPI_POLARITY_HIGH;
  #endif
  hspi.Init.CRCCalculation      = SPI_CRCCALCULATION_DISABLE;
  hspi.Init.CRCPolynomial       = 0xff;
  hspi.Init.DataSize            = SPI_DATASIZE_8BIT;
  hspi.Init.Direction           = SPI_DIRECTION_2LINES;
  hspi.Init.FirstBit            = SPI_FIRSTBIT_MSB;
  hspi.Init.Mode                = SPI_MODE_MASTER;
  hspi.Init.NSS                 = SPI_NSS_SOFT;
  hspi.Init.TIMode              = SPI_TIMODE_DISABLE;
  
  if(HAL_SPI_Init(&hspi) != HAL_OK)
  {
    #if(OPT_DBG_INF > 0U)
    PRINTF_Dbg("SPI1 init failed..\r\n");
    #endif
  }
  
  SPI1_NSS_H;
}

void HAL_SPI_MspInit(SPI_HandleTypeDef * hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  if(hspi->Instance != SPI1){ return ; }
  
  SPI1_NSS_CLK_ENABLE();
  SPI1_CLK_CLK_ENABLE();
  SPI1_MISO_CLK_ENABLE();
  SPI1_MOSI_CLK_ENABLE();
  SPI1_CLK_ENABLE();
  
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Pull  = GPIO_PULLUP;
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pin   = SPI1_NSS_PIN;
  HAL_GPIO_Init(SPI1_NSS_PORT,&GPIO_InitStruct);
  
  GPIO_InitStruct.Mode  = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pin       = SPI1_CLK_PIN;
  GPIO_InitStruct.Alternate = SPI1_SCK_AF;
  HAL_GPIO_Init(SPI1_CLK_PORT,&GPIO_InitStruct);
  
  GPIO_InitStruct.Pin       = SPI1_MOSI_PIN;
  GPIO_InitStruct.Alternate = SPI1_MOSI_AF;
  HAL_GPIO_Init(SPI1_MOSI_PORT,&GPIO_InitStruct);
  
  GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pin       = SPI1_MISO_PIN;
  GPIO_InitStruct.Alternate = SPI1_MISO_AF;
  HAL_GPIO_Init(SPI1_MISO_PORT,&GPIO_InitStruct);
  
  HAL_NVIC_SetPriority(SPI1_IRQn,0x07,0);
  HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
void SPI1_IRQHandler(void)
{
  uint32_t ulBASEPRI = taskENTER_CRITICAL_FROM_ISR();
  
  HAL_SPI_IRQHandler(&hspi);
  
  taskEXIT_CRITICAL_FROM_ISR(ulBASEPRI);
}

/*spi send bytes polling*/
HAL_StatusTypeDef SPI1SendBytes_Polling(uint8_t *pData,uint16_t size)
{
  uint32_t tickStart = xTaskGetTickCount();
  
  SPI1_NSS_L;
  
  while(HAL_SPI_GetState(&hspi) != HAL_SPI_STATE_READY)
  {
    if((xTaskGetTickCount() - tickStart) >= 5U)
    {
      return HAL_TIMEOUT;
    }
  }
  
  tickStart = xTaskGetTickCount();
  if(HAL_SPI_Transmit(&hspi,pData,size,0xff) == HAL_OK)
  {
    while(HAL_SPI_GetState(&hspi) == HAL_SPI_STATE_BUSY_TX)
    {
      if((xTaskGetTickCount() - tickStart) >= 5U)
      {
        return HAL_TIMEOUT;
      }
    }
  }
  else
  {
    return HAL_ERROR;
  }
  
  SPI1_NSS_H;
  
  return HAL_OK;
}

/*spi send bytes it*/
HAL_StatusTypeDef SPI1SendBytes_IT(uint8_t *pData,uint16_t size)
{
  uint32_t tickStart = xTaskGetTickCount();
  
  SPI1_NSS_L;
  
  while(HAL_SPI_GetState(&hspi) != HAL_SPI_STATE_READY)
  {
    if((xTaskGetTickCount() - tickStart) >= 5U)
    {
      return HAL_TIMEOUT;
    }
  }
  
  tickStart = xTaskGetTickCount();
  if(HAL_SPI_Transmit_IT(&hspi,pData,size) == HAL_OK)
  {
    while(HAL_SPI_GetState(&hspi) == HAL_SPI_STATE_BUSY_TX)
    {
      if((xTaskGetTickCount() - tickStart) >= 5U)
      {
        return HAL_TIMEOUT;
      }
    }
  }
  else
  {
    return HAL_ERROR;
  }
  
  SPI1_NSS_H;
  
  return HAL_OK;
}
